/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFParaManager
  \brief a singleton manager class to manage all kinds of parameters globally,
  typically channel id maps, detector positions, calibration constants, and other
  miscellaneous ones.
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-12-03
  \date 2024-05-12 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-12-03   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFParaManager_h
#define ETFParaManager_h

#include <map>
#include <string>
#include <vector>

using std::map;
using std::vector;
using std::string;

class TFile;
class TH1F;

class ETFYaml;
class ETFTask;
class ETFAnalyzer;
class ETFSource;
class ETFGanaPre;
class ETFOfflineSource;
class ETFOnlineSource;

class ETFParaManager{
public:
  static ETFParaManager *Instance();
  virtual ~ETFParaManager();

  const ETFYaml *GetChIdPara() const{ return testnull(fChIdConfig); }
  const ETFYaml *GetDetPosPara() const{ return testnull(fDetPosConfig); }
  const ETFYaml *GetDelayPara() const{ return testnull(fDelayConfig); }
  const ETFYaml *GetMisPara() const{ return testnull(fMisConfig); }
  const ETFYaml *GetOnlinePara() const{ return testnull(fOnlineConfig); }
  const string &configdir() const{ return fConfigDir; }
  const TH1F *GetRTHist(const string &det) const;

  void ReadConfigFiles();
  void ReloadOnlineConfig(); ///< reload to include changes in online.yaml
  bool SetChIdConfigFile(const string &file){ return SetConfigFile(fChIdConfig, file); }
  bool SetDetPosConfigFile(const string &file){ return SetConfigFile(fDetPosConfig, file); }
  bool SetDelayConfigFile(const string &file){ return SetConfigFile(fDelayConfig, file); }
  bool SetMisConfigFile(const string &file){ return SetConfigFile(fMisConfig, file); }
  bool SetOnlineConfigFile(const string &file){ return SetConfigFile(fOnlineConfig, file); }
  bool SetDetMaskConfigFile(const string &file){ return SetConfigFile(fDetMaskConfig, file); }
  virtual void ConfigAnalyzer(ETFAnalyzer *a);
  virtual void ConfigOnlineSource(ETFOnlineSource *s);
  virtual void ConfigOfflineSource(ETFOfflineSource *s);

  virtual void GetOpt(int argc, char *argv[]); ///< parse commandline inputs
  virtual void PromptHelp() const; ///< print help

  virtual void PrintUserInput();
  const string &datafile(int i = 0) const;
  const vector<string> &datafiles() const{ return fDataFiles; }
  int GetRunId() const{ return fRunId; }
  int ev_start() const{ return fIndex0; }
  int ev_stop() const{ return fIndex1; }
  int anaLevel() const{ return fAnaLevel; }
  int ev0() const{ return fIndex0; }
  int ev1() const{ return fIndex1; }
  double MagneticIntensity() const{ return fMagB; }
  bool is3DTrk() const{ return fIs3DTrk; }
  void SetEXE(const string &exe){ fEXE = exe; }
  bool IsReset() const{ return fIsReset; } ///< online reset pressed
  void SetReset(); // beam extraction ends
  void RecoverReset(){ fIsReset = false; } ///< recover online reset
  bool Disabled(const string &name) const;
  
  // ClassDef(ETFParaManager, 0); ///< parameter manager class for ETFAna

  friend class ETFGanaPre; ///< to pass user-input via GUI to this

private:
  ETFParaManager();
  static ETFParaManager *fInstance;

protected:
  /// check if p is null, and issue a warning if so
  static const ETFYaml *testnull(const ETFYaml *p);
  bool SetConfigFile(ETFYaml *&c, const string &file);

  ETFYaml *fChIdConfig; ///< channel id config file
  ETFYaml *fDetPosConfig; ///< detector position config file
  ETFYaml *fDelayConfig; ///< delay calibration constants config file
  ETFYaml *fMisConfig; ///< miscellaneous config file
  ETFYaml *fOnlineConfig; ///< online config file
  ETFYaml *fDetMaskConfig; ///< dets mask config file - to disable dets

  string fConfigDir; ///< config/<exp> defined in exp.yaml
  /// the raw data files to be passed from terminal to internal function ///
  vector<string> fDataFiles; ///< there may be multiple pxi data files
  unsigned fIndex0, fIndex1; ///< [ev_start, ev_stop)
  int fAnaLevel; ///< analysis level: refer to ETFAnalyzer::fAnaLevel for details
  bool fIs3DTrk; ///< whether to conduct 3D tracking in ETFAnalyzer
  bool fIsReset; ///< to transmit online reset signal
  string fEXE; ///< the name of the executable
  double fMagB; ///< magnetic intensity for the big-dipole: in Tesla

  vector<int> fDrawVec; ///< store no. of events to be drawn input via commandline
  int fRunId; ///< the use suffix to the generated rootfile
  vector<string> fDetMask; ///< dets in this will be disabled (not constructed)
  TFile *fRTFile; ///< stores STR hists integrated from drift time distributions
};

#endif
